JSON error when submitting OSO order

I am not sure if my OCO order has all the correct fields. I am trying to test this, but I get an Invalid JSON: illegal number, offset: 0x00000114 JSON error. I am using Python examples from supahcullen/**[Tradovate-Python-Client]. I have this one script I created for a StopOrder with a StopLoss and TakeProfit for testing.

Here is the code. Some variable values are imported and not shown.

#Place TV Stop limit order
import requests
from GetAccessToken import getAccessToken
from config import *
import time

Be careful with this one! It will submit an order!

buysell must be either “Sell” or “Buy”

def placeStopLimitOrder(live, Qty, buysell, orderPrice, stoploss, takeProfit, token):
“”"Places StopLimit order with quantity “Qty”, direction “buysell”, price “orderPrice”, and includes StopLoss and TakeProfit

Args:
    live (bool): True = live, False = demo
    Qty (int): Quantity of contracts you want to buy
    buysell (string): "Buy" or "Sell"
    orderPrice (int): Price you want the order at
    stoploss (double): Stop Price
    takeProfit (double): Take Profit Price
    token (string): User's access token

Returns:
    int: orderId of order you just placed
"""
ocoDirection = ""
if buysell == "Buy":
  ocoDircetion = "Sell"
else:
  ocoDirection = "Buy"
    
header = {
    'Authorization': f'Bearer ${token}', 
    'Accept': 'application/json'
        }

if live:
    url = "https://live.tradovateapi.com/v1/order/placeorder"
    accId = LIVE_ACCOUNT_ID
else:
    url = "https://demo.tradovateapi.com/v1/order/placeorder"
    accId = DEMO_ACCOUNT_ID

order = { 
            "accountSpec": USER_NAME, //imported value
            "accountId": accId, //imported value
            "action": buysell,
            "symbol": SYMBOL, //imported value
            "orderQty": Qty,
            "orderType": "StopLimit",
            "Price": orderPrice,
            "timeInForce": "GTC",
            "isAutomated": "true",
            "bracket1": {
                "action": ocoDirection, //For some reason this is empty
                "orderType": "Stop",
                "price": stoploss,
                "timeInForce": "GTC"
            },
            "bracket2": {
                "action": ocoDirection, //For some reason this is empty
                "orderType": "Stop",
                "price": takeProfit,
                "timeInForce": "GTC"
            }
        }

# Make request
res = requests.post(url, headers=header, data=order)

# Error stuff
if res.status_code != 200:
    print("StopLimit Order Failed")
    print(res.text)
    print(res.status_code)
    print(res.reason)
    print(order)

orderId = res.json()['orderId']

return orderId

This is the error I get back.

StopLimit Order Failed
Invalid JSON: illegal number, offset: 0x00000114
400
Bad Request
{‘accountSpec’: ‘HIDDEN’, ‘accountId’: ‘HIDDEN’, ‘action’: ‘Buy’, ‘symbol’: ‘ESH3’, ‘orderQty’: 1, ‘orderType’: ‘StopLimit’, ‘Price’: 3943, ‘timeInForce’: ‘GTC’, ‘isAutomated’: ‘true’, ‘bracket1’: {‘action’: ‘’, ‘orderType’: ‘Stop’, ‘price’: 3942, ‘timeInForce’: ‘GTC’}, ‘bracket2’: {‘action’: ‘’, ‘orderType’: ‘Stop’, ‘price’: 3944, ‘timeInForce’: ‘GTC’}}
Traceback (most recent call last):
File “C:\Python311\Lib\site-packages\requests\models.py”, line 960, in json
return complexjson.loads(self.content.decode(encoding), **kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Python311\Lib\json_init_.py”, line 346, in loads
return _default_decoder.decode(s)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Python311\Lib\json\decoder.py”, line 337, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “C:\Python311\Lib\json\decoder.py”, line 355, in raw_decode
raise JSONDecodeError(“Expecting value”, s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
File “HIDDEN\Tradovate-Python-Client-main\placestoplimitorder.py”, line 84, in
print(placeStopLimitOrder(False, 1, “Buy”, 3943, 3942, 3944, token))
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File “HIDDEN\Tradovate-Python-Client-main\placestoplimitorder.py”, line 78, in placeStopLimitOrder
orderId = res.json()[‘orderId’]
^^^^^^^^^^
File “C:\Python311\Lib\site-packages\requests\models.py”, line 968, in json
raise RequestsJSONDecodeError(e.msg, e.doc, e.pos)
requests.exceptions.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

What am I missing?? :slight_smile:

I fixed this issue. The values I supplied were not correct or in the right place. Once fixed, I created a new script to place an OCO order with a Take Profit and Stop Loss. The endpoint changes from “placeorder” to “placeOSO” the new order structure that works for this is:

bracket1 = {
        "action": ocoDirection,
        "orderType": "Limit",
        "price": takeProfit
      }
bracket2 = {
        "action": ocoDirection,
        "orderType": "Stop",
        "stopPrice": stoploss
      }

order = {
      "accountSpec": USER_NAME,
      "accountId": accId,
      "action": buysell,
      "symbol": SYMBOL,
      "orderQty": Qty,
      "orderType": "StopLimit",
      "price": orderPrice,
      "stopPrice": orderPrice,
      "isAutomated": True,
      "bracket1": bracket1,
      "bracket2": bracket2
    }

exp:
token = getAccessToken(False)[0]
print(placeStopLimitOrder(False, 1, “Buy”, 3977, 3976.50, 3977.50, token))

ENTRY = 3977
STOPLOSS = 39766.50
TAKE PROFIT = 3977.50

This will place a Stop Limit order with Take Profit and Stop Loss above or below the current market price.

Where:
ocoDirecion = The opposite of the value buysell direction //The variable name should be osoDireection, but it can have any name.
takeProfit = The Take Profit price
stoploss = The Stop Loss price
accid = The Account ID
SYMBOL = The Market being traded
Qty = The quantity
orderPrice = The Entry price
isAutomated = This was in “” and needed to not have quotes -Flag for automated trading

Hey Will,
When you were having this issue did it result in a code 400 bad request error? Having a similar issue and cant for the life of me figure it out

Just to save anyone in the future on placing oso/oco orders via python (super simplified version)

import httpx

auth_token = "Your Auth Token"

params = {
  "accountSpec": "your_username",
  "accountId": account_id_as_integer,
  "action": "Buy", # Buy/Sell
  "symbol": "ESU3", # Symbol to Trade
  "orderQty": 1, # Qty as integer
  "orderType": "Limit", # OrderType
  "price": 4428.00, # Price as integer or float if using Limit/TrailingStopLimit
  "stopPrice": 4220.00, # if using Stop/TrailingStop/TrailingStopLimit
  "isAutomated": True, # Boolean
  "bracket1": {
    "action": "Sell", # Buy/Sell
    "orderType": "Limit", # OrderType
    "price": 4435.00 # Same as comments on price and stopPrice above
  }
}

headers = {
    "Content-Type": "application/json",
    "Accept": "application/json",
    'Authorization': f"Bearer {auth_token}"
}

r = httpx.post(
    "https://demo.tradovateapi.com/v1/order/placeoso",
    headers=headers,
    json=params
)
1 Like