Closed BirajAd closed 2 years ago
Are you sure? How do you do that? I can't seem to be able to place option trades on paper trading
Taking a look at paper trade options, currently web interface is not supported.
Unfortunately, please help me to monitor, if it is supported on the web interface, we will probably be able to add then.
@tedchou12 It works on the Webull Desktop App now. I tried updating it myself but I have no clue how networking works and when the order is placed, there are tons of different packages that are sent. I couldn't find out which one was the right package so I just gave up on it.
unfortunately, it needs to work with the web interface version. (Which is the actual endpoints that this API communicates with)
Ahh. I see. Thats probably why I was so confused.
I have the options paper API endpoints if you're interested in adding this (I'm super busy at the moment)
Can you send it over? I'll try to add it but I'm not sure if it will work as ted said.
Here are the API endpoints:
https://act.webullbroker.com/webull-paper-center/api/paper/v1/order/getOptionAccountDetailAndPosition https://act.webullbroker.com/webull-paper-center/api/paper/v1/order/optionPlace https://act.webullbroker.com/webull-paper-center/api/paper/v1/order/optionReplace
Here is an example function to place option orders:
def place_order_option(self, optionId=None, lmtPrice=None, stpPrice=None, action=None, orderType='LMT', enforce='DAY', quant=0):
'''
create buy / sell order
stock: string
lmtPrice: float
stpPrice: float
action: string BUY / SELL
optionId: string
orderType: MKT / LMT / STP / STP LMT
enforce: GTC / DAY
quant: int
'''
headers = self.build_req_headers(include_trade_token=True, include_time=True)
data = {
'orderType': orderType,
'serialId': str(uuid.uuid4()),
'paperId': 1,
'accountId': self._account_id,
'tickerId': int(optionId),
'quantity': int(quant),
'action': "BUY",
'timeInForce': enforce,
'orders': [{'quantity': int(quant), 'action': action, 'tickerId': int(optionId), 'tickerType': 'OPTION'}],
}
if orderType == 'LMT' and lmtPrice :
data['lmtPrice'] = float(lmtPrice)
elif orderType == 'STP' and stpPrice :
data['auxPrice'] = float(stpPrice)
elif orderType == 'STP LMT' and lmtPrice and stpPrice :
data['lmtPrice'] = float(lmtPrice)
data['auxPrice'] = float(stpPrice)
url = 'https://act.webullbroker.com/webull-paper-center/api/paper/v1/order/optionPlace'
response = requests.post(url, json=data, headers=headers, timeout=self.timeout)
if response.status_code != 200:
raise Exception('place_option_order failed', response.status_code, response.reason)
@michaelkkehoe
Thank you so much! Let me try it out and add to the package as well!
Ted, you got a chance to update the package having those endspoints now? many thanks. @tedchou12
@michaelkkehoe @tedchou12 Have you been successful with a modify option order with the 'https://act.webullbroker.com/webull-paper-center/api/paper/v1/order/optionReplace' endpoint?
I keep getting this response: 2023-05-25 12:42:58,193 INFO b'{"msg":"orderId=null","traceId":"b7ef3d8e73a84dda9b3d8146e2024d20","code":"400","success":false}'
and this is the request: 2023-05-25 12:42:58,192 INFO b'{"oderId": 105353561, "orderType": "LMT", "accountId": 12345, "paperId": 1, "timeInForce": "GTC", "serialId": "XYZ", "orders": [{"quantity": 1, "action": "BUY", "tickerId": 1038356919, "tickerType": "OPTION", "orderId": 105353561}], "lmtPrice": 1.29}'
(intentionally omitted possibly sensitive info)
And here is how I implemented the modify order function in webull.py: def modify_order_option(self, order=None, lmtPrice=None, stpPrice=None, enforce=None, quant=0): ''' order: dict from get_current_orders stpPrice: float lmtPrice: float enforce: GTC / DAY quant: int ''' headers = self.build_req_headers(include_trade_token=True, include_time=True) data = { 'oderId': order[0]['orderId'], 'orderType': order[0]['orderType'], 'accountId': self._account_id, 'paperId': 1, 'timeInForce': enforce or order[0]['timeInForce'], 'serialId': str(uuid.uuid4()), 'orders': [{'quantity': quant or order[0]['totalQuantity'], 'action': order[0]['action'], 'tickerId': order[0]['ticker']['tickerId'], 'tickerType': 'OPTION', 'orderId': order[0]['orderId']}] }
if order[0]['orderType'] == 'LMT' and (lmtPrice or order.get('lmtPrice')):
data['lmtPrice'] = lmtPrice or order[0]['lmtPrice']
elif order[0]['orderType'] == 'STP' and (stpPrice or order.get('auxPrice')):
data['auxPrice'] = stpPrice or order[0]['auxPrice']
elif order[0]['orderType'] == 'STP LMT' and (stpPrice or order.get('auxPrice')) and (lmtPrice or order.get('lmtPrice')):
data['auxPrice'] = stpPrice or order[0]['auxPrice']
data['lmtPrice'] = lmtPrice or order[0]['lmtPrice']
url = 'https://act.webullbroker.com/webull-paper-center/api/paper/v1/order/optionReplace'
response = requests.post(url, json=data, headers=headers, timeout=self.timeout)
logging.info(response.request.body)
logging.info(response.content)
if response.status_code != 200:
raise Exception('replace_option_order failed', response.status_code, response.reason)
return True
The main change I made to the regular account modify_order_option was taking out the "'comboId': order['comboId']" line in the data dictionary as I don't see that in the list of "openOrders" for the paper account. It's somehow not accepting the orderId from the request and I'm not sure why.
Webull now allows options paper trading, if someone could add that as a feature that would be awesome.