Comments (42)
@Robert-Zacchigna Looks like there is a short coming in the pyetrade lib that is corrected by your function. Would you mind opening up a PR that would add your method to the ETradeOrder object? That would be very appreciated I am sure by everyone in the community.
from pyetrade.
Hi, I've been trying to automate some options trades using pytrade/etrade for some months and while I can get individual legs to excersise, there doesn't seem to be support for spreads using pyetrade. Hense I've been looking at your code example here and trying to modify that to suit my needs. Starting with the code as is, I don't seem able to get passed the etrade_oauth part. I see NameError: name 'etrade_oauth' is not defined. Did you mean: 'ETradeOAuth'? Would anyone be able to help me integrate the above code into Jesse's original outh example ?
My code above assumed you already have setup ETradeOAuth and EtradeOrder
For EtradeOAuth, in my case i named the variable etrade_oauth:
etrade_oauth = ETradeOAuth(consumer_key, consumer_secret)
You then need to create the ETradeOrder obj, in my case i named it etrade_order:
etrade_order = ETradeOrder(
consumer_key, consumer_secret,
oauth_token, oauth_secret, dev=False # False for PROD, True for SANDBOX
)
Once the above is done, then you can run my code above, which i think still works. I've made some changes since then i think.
from pyetrade.
For anyone else who comes across this thread, i was unable to get the preview_equity_order
and place_equity_order
functions to work but i was able to come up with this workaround.
You basically need to make the request yourself using the underlying api endpoints instead of the functions. For these function to work, you need to have already setup pyetrades oauth (in my case its etrade_oauth
) and order objs (in my case etrade_order
)
import json
import xmltodict
import xml.etree.ElementTree as ET
from dicttoxml2 import dicttoxml
from pyetrade.order import ETradeOrder
from pyetrade import ETradeAccounts, ETradeOAuth
Function for making the post requests to the etrade api endpoints
def _post_etrade_req(etrade_oauth: ETradeOAuth, etrade_order: ETradeOrder, account_id_key: str,
order_params: dict, post_endpoint: str, print_payload: bool, print_response: bool) -> dict:
order_payload = dicttoxml(order_params, root=False, attr_type=False).decode('UTF-8')
if print_payload:
pretty_xml = ET.XML(order_payload)
ET.indent(pretty_xml)
print(f'\n{post_endpoint.capitalize()} Order Request XML Payload:\n{"="*(27+len(post_endpoint))}\n'
f'{ET.tostring(pretty_xml, encoding="unicode")}')
headers = {"consumerKey": etrade_oauth.consumer_key, 'Content-Type': 'application/xml'}
post_endpoint_url = f'https://api.etrade.com/v1/accounts/{account_id_key}/orders/{post_endpoint}'
order_response = etrade_order.session.post(post_endpoint_url, headers=headers, data=order_payload)
order_data = json.loads(json.dumps(xmltodict.parse(order_response.text)))
if print_response:
print(f'\n{post_endpoint.capitalize()} Order JSON Response:\n{"="*(21+len(post_endpoint))}\n'
f'{json.dumps(order_data, indent=4)}')
return order_data
My preview_shares_order
function - this returns the preview_order_params and the preview_id from the preview_order_response:
# order_action_values = ['BUY', 'SELL', 'BUY_TO_COVER', 'SELL_SHORT']
# price_types_values = ['MARKET', 'LIMIT', 'STOP', 'STOP_LIMIT', 'MARKET_ON_CLOSE']
# market_session_values = ['REGULAR', 'EXTENDED']
# order_term_values = ['GOOD_UNTIL_CANCEL', 'GOOD_FOR_DAY', 'IMMEDIATE_OR_CANCEL', 'FILL_OR_KILL']
# routing_destinations_values = ['AUTO', 'ARCA', 'NSDQ', 'NYSE']
# Reference number generated by developer. Used to ensure duplicate order is not submitted.
# Value can be of 20 alphanmeric characters or less Must be unique within this account.
# Does not appear in any API responses.
# Ref: https://apisb.etrade.com/docs/api/order/api-order-v1.html#/definitions/OrderDetail
def preview_shares_order(etrade_oauth: ETradeOAuth, etrade_order: ETradeOrder, account_id_key: str, symbol: str,
limit_price: float, quantity: int, print_payload: bool, print_response: bool,
order_type: str = 'EQ', order_action: str = 'BUY', all_or_none: bool = False,
client_order_id: str = str(randint(1000000000, 9999999999)), stop_price: float = 0,
price_type: str = 'LIMIT', market_session: str = 'REGULAR',
order_term: str = 'IMMEDIATE_OR_CANCEL', routing_destination: str = 'AUTO') -> tuple[dict, int]:
preview_order_params = {
'PreviewOrderRequest': {
'orderType': order_type,
'clientOrderId': client_order_id,
'Order': {
'allOrNone': all_or_none,
'priceType': price_type,
'orderTerm': order_term,
'marketSession': market_session,
'stopPrice': stop_price,
'limitPrice': limit_price,
'routingDestination': routing_destination,
'Instrument': {
'Product': {
'securityType': 'EQ',
'symbol': symbol
},
'orderAction': order_action,
'quantityType': 'QUANTITY',
'quantity': quantity,
}
}
}
}
preview_order_data = _post_etrade_req(etrade_oauth, etrade_order, account_id_key, preview_order_params,
'preview', print_payload, print_response)
return preview_order_params['PreviewOrderRequest'], preview_order_data['PreviewOrderResponse']['PreviewIds']['previewId']
My place_shares_order
function, this is similar to the above function. This takes the preview_order_params and the preview_id from the preview_shares_order function to make the equity order. It will check and display if the order is successful or not:
def place_shares_order(etrade_oauth: ETradeOAuth, etrade_order: ETradeOrder, account_id_key: str,
preview_order_params: dict, preview_id: int, print_payload: bool, print_response: bool) -> None:
# Insert preview_order_params and preview_id into new place_shares_order payload
place_order_params = {'PlaceOrderRequest': preview_order_params}
place_order_params['PlaceOrderRequest']['PreviewIds'] = {'previewId': preview_id}
place_order_data = _post_etrade_order_req(etrade_oauth, etrade_order, account_id_key, place_order_params, 'place',
print_payload, print_response)['PlaceOrderResponse']['Order']['messages']['Message']
for index, msg_codes in enumerate(place_order_data):
order_msg_code = msg_codes['code']
order_msg_desc = msg_codes['description'].replace('|', ' - ')
# Order success code = 1026
# Ref: https://apisb.etrade.com/docs/api/order/api-order-v1.html#/definitions/ErrorCodes
if order_msg_code != '1026' and index + 1 == len(place_order_data):
raise ValueError(f"Order Msg Code: {order_msg_code}\n Description: {order_msg_desc}")
print(f"Order Msg Code: {order_msg_code}\n Description: {order_msg_desc}\n")
And calling them:
preview_order_params, preview_id = preview_shares_order(etrade_oauth, etrade_order, account_id_key, 'CVNA',
1.00, 1, print_payload=False, print_response=False)
place_shares_order(etrade_oauth, etrade_order, account_id_key, preview_order_params,
preview_id, print_payload=False, print_response=False)
If successful your output should be:
Order Msg Code: 1026
Description: 200 - Your order was successfully entered during market hours.
You can verify even further by printing out your order history:
print('Orders:', etrade_order.list_orders(account_id_key, resp_format='json'))
from pyetrade.
After one day of digging, I found the root cause of this stupid issue. The string key "previewIds" need be capitalized as "PreviewIds". Otherwise, the server won't recognize the previewId parameter.
from pyetrade.
Thanks @Robert-Zacchigna that's working fine now for equity orders ! I will modify the fields to support Options orders insteadf of Equity orders and hopefully eventually get a spread to work also. Much apprecaited.
from pyetrade.
@Robert-Zacchigna Thank you for doing this. Give me a bit of time to look at the changes.
from pyetrade.
Hello yangliu2. I am also having the same issue. Matter of fact I am not even able to execute the preview_equity_order() function. Getting "missing kwargs" error. Below are the details. Hope I am not hijacking your issue request but would you know what is causing this issue since I see you are able to execute preview_equity_order?
if not all(param in kwargs for param in mandatory):
--> 135 raise OrderException
136
137 if kwargs["priceType"] == "STOP" and "stopPrice" not in kwargs
Below is the kwargs dictionary I am using in SandBox environment
kwargs = {
"accountId":"6_Dpy0rmuQ9cu9IbTfvF2A",
"symbol":"AAPL",
"orderAction":"BUY",
"clientOrderId": random.randint(10000000,99999999),
"priceType":"MARKET",
"allOrNone": True,
"limitPrice":0,
"stopPrice":0,
}
from pyetrade.
No problem man! I'm having the same error. I manually checked the required keys AND modified source code to check if "mandatory" have it. No luck. I don't know what's it's checking. This is where I went to Etrade sample code instead. Also remember trade sandbox have fixed response for preview and place order, so you need to make sure your placing order payload is the same as the preview response, not whatever payload you send it to them. Now I'm sticking on error 9999 for placing order.
from pyetrade.
Hello yangliu2
Thanks for your response. After trying a few things was able to make the preview order and place order to work. You simply have to make sure your kwargs dictionary is in the order in the mandatory list in the check order() function.
mandatory = ["accountId","symbol","orderAction","clientOrderId","priceType","quantity","orderTerm","marketSession"]
Ofcourse remember to use ** before kwargs in the paranthesis to show its a dictionary.
All this was in dev environment. I haven't tried actual prod environment..
Let me know how it goes.
from pyetrade.
Test these kwarg keys values,
kwargs = {"accountId":"6_Dpy0rmuQ9cu9IbTfvF2A",
"symbol":"GOGL",
"orderAction":"BUY",
"clientOrderId": random.randint(10000000,99999999),
"priceType":"MARKET",
"allOrNone": True,
"limitPrice":0,
"stopPrice":0,
"quantity":100,
"orderTerm":"GOOD_FOR_DAY",
"marketSession":"REGULAR"
}
Then after you instantiate the ETradeOrder class and create an object try calling the method below
myfirstorder.preview_equity_order(**kwargs)
from pyetrade.
For some reason, if I use resp_format='json'
, then I get a 400 response error. Without the parameter, it seems to be fine. ¯\_(ツ)_/¯
from pyetrade.
from pyetrade.
Hello yangliu2,
I am also facing exact same issue which you faced. Please let me know how you resolved this.
Thanks a lot.
from pyetrade.
Hi, @yangliu2 were you able to resolve this and place order successfully from python code?
from pyetrade.
from pyetrade.
I am also trying to place an order with the ETrade API and got the following error:
{'code': 101, 'message': 'For your protection, we have timed out your original order request. If you would like to place this order, please resubmit it now.'}
the preview order seems to be working ok. If anyone figures how to successfully place an order please let me know, thanks!
from pyetrade.
@yangliu2 could you please share the code ETrade support provides?
Thanks!
from pyetrade.
from pyetrade.
Here is the code I got from Etrade. There weren't any formating, so you may have to retype.
Below is a simple method for place order. Make sure you copy the fields from preview order into your place order and you have to pass the previewId from the response from the preview order into the place order request or it will not work. Should you questions feel free to reply to this message.
def place_order(session, account, order):
"""
Calls place order API to submit an order request for confirmation after preview order is successfully called
:param session: authenticated session
:param account: information on selected account
:param order: list of instruments from previous orders
"""
URL for the API endpoint
url = "https://api.etrade.com/v1/accounts/" + account["accountIdKey"]+ "/orders/place.json"
Add parameters and header information
headers = {"Content-Type": "application/xml", "consumerKey": config["DEFAULT"]["CONSUMER_KEY"]}
Add payload for POST Request
payload = """
{0}
{1}
{2}
false
{3}
{4}
REGULAR
{5}
{6}
{7}
{8}
QUANTITY
{9}
"""
payload = payload.format(order["order_type"], order["client_order_id"], order["preview_id"],
order["price_type"], order["order_term"], order["limitPrice"],
order["security_type"], order["symbol"], order["order_action"], order["quantity"])
Make API call for POST request
response = session.post(url, header_auth=True, headers=headers, data=payload)
logger.debug("Request Header: %s", response.request.headers)
logger.debug("Request payload: %s", payload)
Handle and parse response
if response is not None and response.status_code == 200:
parsed = json.loads(response.text)
logger.debug("Response Body: %s", json.dumps(parsed, indent=4, sort_keys=True))
data = response.json()
print("\nOrder number #"
+ str(data["PlaceOrderResponse"]["OrderIds"][0]["orderId"])
+ " successfully placed.")
else:
Handle errors
data = response.json()
if 'Error' in data and 'message' in data["Error"]and data["Error"]["message"]is not None:
print("Error: " + data["Error"]["message"])
else:
print("Error: Preview Order API service error")
from pyetrade.
Thanks @yangliu2 !
"Make sure you copy the fields from preview order into your place order and you have to pass the previewId from the response from the preview order into the place order request or it will not work."
This comment is really useful! I tried to include the previewID and now placing the order works!
Thanks a lot!
from pyetrade.
@yangliu2 Can you please open a PR with any changes that are needed in pyetrade to better support this?
from pyetrade.
Thanks @yangliu2 !
"Make sure you copy the fields from preview order into your place order and you have to pass the previewId from the response from the preview order into the place order request or it will not work."
This comment is really useful! I tried to include the previewID and now placing the order works!
Thanks a lot!
I tried including the previewId in the order but I still get error 400 after the place_equity_order is called. Any clue why this isn't working??
resp = orders.preview_equity_order(
accountId=self.account_id,
symbol="IBM",
orderAction="BUY",
clientOrderId="1",
priceType="MARKET",
quantity="1",
orderTerm="GOOD_UNTIL_CANCEL",
marketSession="REGULAR"
)
preview_id = resp['PreviewOrderResponse']['PreviewIds']['previewId'].get_cdata()
resp = orders.place_equity_order(
previewId=preview_id,
accountId=self.account_id,
symbol="IBM",
orderAction="BUY",
clientOrderId="1",
priceType="MARKET",
quantity="1",
orderTerm="GOOD_UNTIL_CANCEL",
marketSession="REGULAR"
)
from pyetrade.
I've tried all of above solutions but None is working for me, place order keep responding same error and preview order working correctly
from pyetrade.
Looots of inconsistency in Etrade API. Sometimes the first character is capped and sometimes it isn't.
from pyetrade.
I do have another issue with etrade api. During authentication, from time to time, I got this error. All I can do is to restart the code and then it could pass without error.
Exception has occurred: UnicodeDecodeError
'ascii' codec can't decode byte 0xe2 in position 60: ordinal not in range(128)
File "I:\projects\EtradePythonClient\auto_trade.py", line 577, in
session = etrade.get_auth_session(request_token,
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 60: ordinal not in range(128)
from pyetrade.
For anyone else who comes across this thread, i was unable to get the
preview_equity_order
andplace_equity_order
functions to work but i was able to come up with this workaround.You basically need to make the request yourself using the underlying api endpoints instead of the functions. For these function to work, you need to have already setup pyetrades oauth obj (in my case its
etrade_oauth
)import json import xmltodict import xml.etree.ElementTree as ET from dicttoxml2 import dicttoxml from pyetrade.order import ETradeOrder from pyetrade import ETradeAccounts, ETradeOAuthFunction for making the post requests to the etrade api endpoints
def _post_etrade_req(etrade_oauth: ETradeOAuth, etrade_order: ETradeOrder, account_id_key: str, order_params: dict, post_endpoint: str, print_payload: bool, print_response: bool) -> dict: order_payload = dicttoxml(order_params, root=False, attr_type=False).decode('UTF-8') if print_payload: pretty_xml = ET.XML(order_payload) ET.indent(pretty_xml) print(f'\n{post_endpoint.capitalize()} Order Request XML Payload:\n{"="*(27+len(post_endpoint))}\n' f'{ET.tostring(pretty_xml, encoding="unicode")}') headers = {"consumerKey": etrade_oauth.consumer_key, 'Content-Type': 'application/xml'} post_endpoint_url = f'https://api.etrade.com/v1/accounts/{account_id_key}/orders/{post_endpoint}' order_response = etrade_order.session.post(post_endpoint_url, headers=headers, data=order_payload) order_data = json.loads(json.dumps(xmltodict.parse(order_response.text))) if print_response: print(f'\n{post_endpoint.capitalize()} Order JSON Response:\n{"="*(21+len(post_endpoint))}\n' f'{json.dumps(order_data, indent=4)}') return order_dataMy
preview_shares_order
function - this returns the preview_order_params and the preview_id from the preview_order_response:# order_action_values = ['BUY', 'SELL', 'BUY_TO_COVER', 'SELL_SHORT'] # price_types_values = ['MARKET', 'LIMIT', 'STOP', 'STOP_LIMIT', 'MARKET_ON_CLOSE'] # market_session_values = ['REGULAR', 'EXTENDED'] # order_term_values = ['GOOD_UNTIL_CANCEL', 'GOOD_FOR_DAY', 'IMMEDIATE_OR_CANCEL', 'FILL_OR_KILL'] # routing_destinations_values = ['AUTO', 'ARCA', 'NSDQ', 'NYSE'] # Reference number generated by developer. Used to ensure duplicate order is not submitted. # Value can be of 20 alphanmeric characters or less Must be unique within this account. # Does not appear in any API responses. # Ref: https://apisb.etrade.com/docs/api/order/api-order-v1.html#/definitions/OrderDetail def preview_shares_order(etrade_oauth: ETradeOAuth, etrade_order: ETradeOrder, account_id_key: str, symbol: str, limit_price: float, quantity: int, print_payload: bool, print_response: bool, order_type: str = 'EQ', order_action: str = 'BUY', all_or_none: bool = False, client_order_id: str = str(randint(1000000000, 9999999999)), stop_price: float = 0, price_type: str = 'LIMIT', market_session: str = 'REGULAR', order_term: str = 'IMMEDIATE_OR_CANCEL', routing_destination: str = 'AUTO') -> tuple[dict, int]: preview_order_params = { 'PreviewOrderRequest': { 'orderType': order_type, 'clientOrderId': client_order_id, 'Order': { 'allOrNone': all_or_none, 'priceType': price_type, 'orderTerm': order_term, 'marketSession': market_session, 'stopPrice': stop_price, 'limitPrice': limit_price, 'routingDestination': routing_destination, 'Instrument': { 'Product': { 'securityType': 'EQ', 'symbol': symbol }, 'orderAction': order_action, 'quantityType': 'QUANTITY', 'quantity': quantity, } } } } preview_order_data = _post_etrade_req(etrade_oauth, etrade_order, account_id_key, preview_order_params, 'preview', print_payload, print_response) return preview_order_params['PreviewOrderRequest'], preview_order_data['PreviewOrderResponse']['PreviewIds']['previewId']My
place_shares_order
function, this is similar to the above function. This takes the preview_order_params and the preview_id from the preview_shares_order function to make the equity order. It will check and display if the order of successful or not:def place_shares_order(etrade_oauth: ETradeOAuth, etrade_order: ETradeOrder, account_id_key: str, preview_order_params: dict, preview_id: int, print_payload: bool,print_response: bool) -> None: # Insert preview_order_params and preview_id into new place_shares_order payload place_order_params = {'PlaceOrderRequest': preview_order_params} place_order_params['PlaceOrderRequest']['PreviewIds'] = {'previewId': preview_id} place_order_data = _post_etrade_req(etrade_oauth, etrade_order, account_id_key, place_order_params, 'place', print_payload, print_response) order_msg_code = place_order_data['PlaceOrderResponse']['Order']['messages']['Message']['code'] order_msg_desc = place_order_data['PlaceOrderResponse']['Order']['messages']['Message']['description'].replace('|', ' - ') # Order success code = 1026 # Ref: https://apisb.etrade.com/docs/api/order/api-order-v1.html#/definitions/ErrorCodes if order_msg_code != '1026': raise ValueError(f"Order Msg Code: {order_msg_code}\n Description: {order_msg_desc}") print(f"\nOrder Msg Code: {order_msg_code}\n Description: {order_msg_desc}\n")And calling them:
preview_order_params, preview_id = preview_shares_order(etrade_oauth, etrade_order, account_id_key, 'CVNA', 1.00, 1, print_payload=False, print_response=False) place_shares_order(etrade_oauth, etrade_order, account_id_key, preview_order_params, preview_id, print_payload=False, print_response=False)If successful your output should be:
Order Msg Code: 1026 Description: 200 - Your order was successfully entered during market hours.
You can verify even further by printing out your order history:
print('Orders:', etrade_order.list_orders(account_id_key, resp_format='json'))
from pyetrade.
Hi, I've been trying to automate some options trades using pytrade/etrade for some months and while I can get individual legs to excersise, there doesn't seem to be support for spreads using pyetrade. Hense I've been looking at your code example here and trying to modify that to suit my needs. Starting with the code as is, I don't seem able to get passed the etrade_oauth part. I see NameError: name 'etrade_oauth' is not defined. Did you mean: 'ETradeOAuth'? Would anyone be able to help me integrate the above code into Jesse's original outh example ?
from pyetrade.
@m4rkyt No problem, glad you were able to make it work.
@jessecooper I'd be happy to, i haven't looked too deeply into the source code so it might take me a little bit to get up to speed. By method do you mean _post_etrade_req
or do you mean a fix for the preview_equity_order
and place_equity_order
functions in order.py
?
from pyetrade.
@m4rkyt No problem, glad you were able to make it work.
@jessecooper I'd be happy to, i haven't looked too deeply into the source code so it might take me a little bit to get up to speed. By method do you mean
_post_etrade_req
or do you mean a fix for thepreview_equity_order
andplace_equity_order
functions inorder.py
?
The fix for preview_equity_order
and place_equity_order
in order.py
from pyetrade.
@jessecooper Ok so after digging through some things, I was actually able to get the functions already in order.py
to work and place equity orders. You'll notice for both of them that i dont have resp_format specified.
This works to retrieve a previewId:
client_order_id = str(randint(1000000000, 9999999999))
preview_id = etrade_order.preview_equity_order(accountId=account_id_key, symbol='SPY', clientOrderId=client_order_id, limitPrice=300.0,
quantity=1, orderType='EQ', orderAction='BUY', allOrNone=False, stopPrice=0,
priceType='LIMIT', marketSession='REGULAR', orderTerm='FILL_OR_KILL',
routingDestination='AUTO')['PreviewOrderResponse']['PreviewIds']['previewId']
print('PreviewID:', preview_id)
This code also successfully places the equity order without a previewId (verified in etrade under the orders tab):
client_order_id = str(randint(1000000000, 9999999999))
kwargs = {'accountId': account_id_key, 'symbol': 'SPY', 'orderAction': 'BUY', 'clientOrderId': client_order_id,
'priceType': 'LIMIT', 'quantity': 1, 'orderTerm': 'FILL_OR_KILL', 'marketSession': 'REGULAR', 'limitPrice': 300,
'orderType': 'EQ', 'allOrNone': False, 'stopPrice': 0, 'routingDestination': 'AUTO'}
print(etrade_order.place_equity_order(**kwargs))
AND
client_order_id = str(randint(1000000000, 9999999999))
print(etrade_order.place_equity_order(accountId=account_id_key, symbol='SPY', orderAction='BUY',
clientOrderId=client_order_id, priceType='LIMIT', quantity=1,
orderTerm='FILL_OR_KILL', marketSession='REGULAR', limitPrice=300,
orderType='EQ', allOrNone=False, stopPrice=0, routingDestination='AUTO'))
Looking at it all, i think whats going on is a combination of misunderstanding the variable accountId
name, the json
resp_format option and what the kwargs
payload should look like.
- First, the
accountId
param, this is kinda confusing because the etrade accountId is actually the 8 digit number in etrade, where these requests require the accountId key to make the request (retrieved from theetrade_accounts.list_accounts()
function). Therefore, my recommendation would be to change the name of the param toaccountIdKey
instead. - Second, for whatever reason specifying
json
for the resp_format for either of these function always results in ahttp 500 error
(no matter what i tried to get it to work). Since it appears that the etrade API randomly supports json and xml in various areas (honestly what the heck were these devs doing then they created the API), my recommendation would be to hard codexml
as the format for these functions to avoid this issue. - Lastly, I think the final part of this is that people might be creating the
kwargs
payload incorrectly, thus throwing the 500 error once more due to the incorrect params. My recommendation would be to either provide an example in the documentation of what a basic payload should look like OR, instead of utilizing kwargs, specify the params directly in the function to avoid the confusion and allow function hinting on what is needed and what is optional for the request (for both preview and place).
I can make the PR if you agree with the above, but please double check yourself that what i stated above is the same for you before we make any changes. Let me know what you find and if you agree with my assessment, thanks.
from pyetrade.
I do agree. The orders.py
module is actually fairly older code and is not following the same patterns as refactored modules like the accounts.py
module.
The newer modules all use xmltodict
(https://github.com/jessecooper/pyetrade/blob/master/pyetrade/accounts.py#L10) and all methods are defaulted to xml
(https://github.com/jessecooper/pyetrade/blob/master/pyetrade/accounts.py#L61).
Like you have noticed the json
support is spotty for whatever reason in the ETrade API. I have been meaning to refactor all modules to follow this new pattern and use type hints where possible. I agree with all your above assertions and would really appreciated the contribution and modernization of that orders module. Thanks in advance.
from pyetrade.
@jessecooper Sounds good, I've given it all a first run through, please check it out here and let me know what you think: #78
from pyetrade.
... hopefully eventually get a spread to work also.
@m4rkyt are you able to get the spread to work? can you create a PR to share the code?
from pyetrade.
Hi @mw66,
Currently my code still places all option legs individually and waits for confirmation on long fills before placing the short since my account won't let me trade naked shorts. It's a bit messy doing this as I can lose a few seconds waiting for confirmation of a fill so I do plan to modify this to use a spread. I will try this over the next couple of weeks and report back.
from pyetrade.
... hopefully eventually get a spread to work also.
@m4rkyt are you able to get the spread to work? can you create a PR to share the code?
I'd love to see the spread order working too.
from pyetrade.
Hi all, I'm new here. I'm trying to call the preview_equity_order
method along with the place_equity_order
method. I have a pretty lengthy question with two parts (1 is for options order, 2 is for equity order). I'm sure I'm doing something wrong somewhere and I'd appreciate some assistance with order functionality!
- I attempted to place an option order but I get the following response:
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='api.etrade.com', port=443): Read timed out.
Below is what I pass in to preview_equity_order
etrade_order.preview_equity_order(
securityType="OPTN",
orderType="OPTN",
accountIdKey="XXXXXXXXXXXXXX",
symbol="BAC",
orderAction="SELL_CLOSE",
clientOrderId="6591041807",
priceType="MARKET",
quantity=3,
callPut="CALL",
expiryDate=datetime.datetime(2023,4,21), # modified to take datetime object
marketSession="REGULAR",
orderTerm= "GOOD_FOR_DAY",
strikePrice=30
)
Here is the Payload
{
'PreviewOrderRequest': {
'orderType': 'OPTN',
'clientOrderId': '6591041807',
'Order': {
'securityType': 'OPTN',
'orderType': 'OPTN',
'accountIdKey': 'zBRmF6b_gzE-mkO74Vbaag',
'symbol': 'BAC',
'orderAction': 'SELL_CLOSE',
'clientOrderId': '6591041807',
'priceType': 'MARKET',
'quantity': 3,
'callPut': 'CALL',
'marketSession': 'REGULAR',
'orderTerm': 'GOOD_FOR_DAY',
'strikePrice': 30, 'Instrument': {
'Product': {
'securityType': 'OPTN',
'symbol': 'BAC',
'expiryDay': 21,
'expiryMonth': 4,
'expiryYear': 2023,
'callPut': 'CALL',
'strikePrice': 30
},
'orderAction': 'SELL_CLOSE',
'quantityType': 'QUANTITY',
'quantity': 3
}
}
}
}
- Also having an issue when trying to place an equity order.
etrade_order.preview_equity_order(
securityType="EQ",
orderType="EQ",
accountIdKey="XXXXXXXXXXXXXX",
symbol="AAPL",
orderAction="SELL",
clientOrderId="6591041907",
priceType="MARKET",
quantity=1,
marketSession="REGULAR",
orderTerm="GOOD_FOR_DAY",
)
Below is the preview order request.
{
'PreviewOrderRequest': {
'orderType': 'EQ',
'clientOrderId': '6591041907',
'Order': {
'securityType': 'EQ',
'orderType': 'EQ',
'accountIdKey': 'XXXXXXXXXXXXXXX,
'symbol': 'AAPL',
'orderAction': 'SELL',
'clientOrderId': '6591041907',
'priceType': 'MARKET',
'quantity': 1,
'marketSession': 'REGULAR',
'orderTerm': 'GOOD_FOR_DAY',
'Instrument': {
'Product': {
'securityType': 'EQ',
'symbol': 'AAPL'
},
'orderAction': 'SELL',
'quantityType': 'QUANTITY',
'quantity': 1
}
}
}
}
I get the following response:
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='api.etrade.com', port=443): Read timed out.
Thanks for taking a look!
-Kori
from pyetrade.
@korivernon I havent seen that error before, could be something with your network or something else.
- Are you able to make other calls with the api?
- Did you try this during trading hours or after hours?
- Furthermore, one of the weird quirks of the API is that it wont let you preview or attempt to place an equity order if the order itself is more than the available cash you have to spend in your account. Don't know why it is that way, just something I've observed during my usage with the API.
- Although that would usually kick out a different error than the one above (which is why i think it could be something with your network connection).
from pyetrade.
from pyetrade.
I'm still getting an issue trying to submit my order (using my own order version) during market hours... Successfully Previews but I get this
Error: For your protection, we have timed out your original order request. If you would like to place this order, please resubmit it now.
When I use the order functionality from EtradeOrder, I get this issue:
xml.parsers.expat.ExpatError: not well-formed (invalid token): line 1, column 4
Does anyone mind sending their kwargs
with sensitive information redacted? Below are mine for an options order. I modified to take in datetime object
{'securityType': 'OPTN',
'orderType': 'OPTN',
'accountIdKey': 'XXXXXXXXXXX',
'symbol': 'BAC',
'orderAction': 'SELL_CLOSE',
'clientOrderId': '6591041807',
'priceType': 'MARKET',
'quantity': 3,
'callPut': 'CALL',
'expiryDate': datetime.datetime(2023, 4, 21, 0, 0),
'marketSession': 'REGULAR',
'orderTerm': 'GOOD_FOR_DAY',
'strikePrice': 30}
Thanks,
Kori
from pyetrade.
@korivernon I think you might be missing some params, try adding these 3 params as well to your kwargs:
"allOrNone": False, "stopPrice": 0, "routingDestination": 'AUTO'
The etrade api uses a mix of json and xml endpoints (who knows why), so the error above seems to indicate the xml payload is malformed (which could be the result of missing params).
I dont have much experience with options orders but it should be similar enough to equity orders.
from pyetrade.
@korivernon I think you might be missing some params, try adding these 3 params as well to your kwargs:
"allOrNone": False, "stopPrice": 0, "routingDestination": 'AUTO'The etrade api uses a mix of json and xml endpoints (who knows why), so the error above seems to indicate the xml payload is malformed (which could be the result of missing params).
I dont have much experience with options orders but it should be similar enough to equity orders.
It seems like that may have done the trick!
Sometimes the read times out. Other times it seems to execute without issue. This may be because I'm trying to place the order outside of market hours, so I'll give it another try in the morning.
In the meantime, have you ever gotten this:
requests.exceptions.ConnectionError: HTTPSConnectionPool(host='api.etrade.com', port=443): Read timed out.
Additionally, when it "seems to run without issue," this is the dictionary that is the result of the preview_equity_order
function. This is not because I'm outside of market hours, as I would expect a 200 response ( 200 | The market was closed when we received your order. It has been entered into our system and will be reviewed prior to market open on the next regular trading day. After market open, please check to make sure your order was accepted.).
{'html': {'body': {'b': 'Http/1.1 400 Bad Request'}}}
Here are the kwargs I'm passing in:
{
'securityType': 'OPTN',
'orderType': 'OPTN',
'accountIdKey': 'XXXXXXXXXX',
'symbol': 'BAC',
'orderAction': 'SELL_CLOSE',
'clientOrderId': '6591041807',
'priceType': 'MARKET',
'quantity': 3,
'callPut': 'CALL',
'expiryDate': datetime.datetime(2023, 4, 21, 0, 0),
'marketSession': 'REGULAR',
'orderTerm': 'GOOD_FOR_DAY',
'strikePrice': 30,
'allOrNone': False,
'stopPrice': 0,
'routingDestination': 'AUTO'
}
from pyetrade.
I see you mentioned using a custom order function, did you by chance specify a timeout in the request? From what i can tell its possible the timeout is being reached before the request has time to be completed.
As for the 400 error im not too sure, it strange that it happens when you call the preview_equity_order
function directly and not when you try to place an equity as well.
I say that because if you look at the code for the order functions, preview_equity_order
is called within the place_equity_order
function and the place_options_order
function calls the place_equity_order
function.
- Just to be clear: option_order -> place_order -> preview_order
If the order is executed then i wouldn't be too concerned about it, i would take a guess that it might be related to the timeout issue.
from pyetrade.
Related Issues (20)
- Are contingent orders actually supported? HOT 1
- oauth problems HOT 1
- oauth issue HOT 6
- [Warning!] ETrade API *sever* bug: Stop Price and Trailing Stop Parameter are swapped! HOT 3
- Preview order working but place order responding with same error again and again. HOT 1
- Verification code HOT 2
- Automatic Authentication HOT 2
- 401 Client Error: Unauthorized for URL in prod HOT 1
- auth server down on 2022-06-29
- 401 Client Error: Unauthorized for url HOT 2
- HTTPError: 401 Client Error: Unauthorized for url HOT 1
- oauth no longer working HOT 8
- Keep getting requests.exceptions.HTTPError: 400 Client Error: Bad Request for url when trying to place options order. HOT 8
- Exception: 500 Server Error: Internal Server Error for url When using preview_equity_order function
- Question about Etrade API HOT 2
- get_quote for an option call returns the put HOT 1
- Q: anyone saw this error: Token request failed with code 500 HOT 2
- SSL errors with Python 3.11 HOT 14
- urllib3 version needs to be 1.xx.xx HOT 2
- Cannot grab optionchain data with ETrade API in Python HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from pyetrade.