E*TRADE API报101超时错误:下单重试仍失败问题排查
E*TRADE API 下单超时错误排查
错误信息
Failed to place BUY order for JAN, status code: 400, response: {"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."}}
问题描述
已在代码中设置最多3次重试逻辑,但每次尝试下单仍返回上述超时保护错误,代码调用逻辑无误。
核心代码
def preview_order(etrade, session, ticker, quantity, limit_price, order_action): preview_url = etrade.base_url + "/v1/accounts/" + ETRADE_ACCOUNT_KEY + "/orders/preview.json" client_order_id = random.randint(1000000000, 9999999999) limit_price_rounded = "{:.2f}".format(limit_price) root = ET.Element("PreviewOrderRequest") ET.SubElement(root, "orderType").text = "EQ" ET.SubElement(root, "clientOrderId").text = str(client_order_id) order = ET.SubElement(root, "Order") ET.SubElement(order, "allOrNone").text = "false" ET.SubElement(order, "priceType").text = "LIMIT" ET.SubElement(order, "orderTerm").text = "GOOD_FOR_DAY" ET.SubElement(order, "marketSession").text = "REGULAR" ET.SubElement(order, "limitPrice").text = limit_price_rounded instrument = ET.SubElement(order, "Instrument") product = ET.SubElement(instrument, "Product") ET.SubElement(product, "securityType").text = "EQ" ET.SubElement(product, "symbol").text = ticker ET.SubElement(instrument, "orderAction").text = order_action.upper() ET.SubElement(instrument, "quantityType").text = "QUANTITY" ET.SubElement(instrument, "quantity").text = str(quantity) payload = ET.tostring(root, encoding='unicode') headers = {"Content-Type": "application/xml"} response = session.post(preview_url, header_auth=True, headers=headers, data=payload) if response.status_code == 200: response_data = response.json() if "PreviewOrderResponse" in response_data and "PreviewIds" in response_data["PreviewOrderResponse"]: preview_id = response_data["PreviewOrderResponse"]["PreviewIds"][0]["previewId"] return preview_id else: print("Preview order response is not as expected.") return None else: print(f"Failed to preview order, status code: {response.status_code}, response: {response.text}") return None def place_order(etrade, session, ticker, quantity, limit_price, order_action, max_attempts=3): attempt = 1 while attempt <= max_attempts: preview_id = preview_order(etrade, session, ticker, quantity, limit_price, order_action) if not preview_id: print("Failed to preview the order.") if attempt == max_attempts: return None else: print(f"Retrying preview order... Attempt {attempt} of {max_attempts}") attempt += 1 continue order_url = etrade.base_url + "/v1/accounts/" + ETRADE_ACCOUNT_KEY + "/orders/place.json" limit_price_rounded = "{:.2f}".format(limit_price) client_order_id = random.randint(1000000000, 9999999999) root = ET.Element("PlaceOrderRequest") ET.SubElement(root, "orderType").text = "EQ" ET.SubElement(root, "clientOrderId").text = str(client_order_id) ET.SubElement(root, "PreviewId").text = str(preview_id) order = ET.SubElement(root, "Order") ET.SubElement(order, "allOrNone").text = "false" ET.SubElement(order, "priceType").text = "LIMIT" ET.SubElement(order, "orderTerm").text = "GOOD_FOR_DAY" ET.SubElement(order, "marketSession").text = "REGULAR" ET.SubElement(order, "limitPrice").text = limit_price_rounded instrument = ET.SubElement(order, "Instrument") product = ET.SubElement(instrument, "Product") ET.SubElement(product, "securityType").text = "EQ" ET.SubElement(product, "symbol").text = ticker ET.SubElement(instrument, "orderAction").text = order_action.upper() ET.SubElement(instrument, "quantityType").text = "QUANTITY" ET.SubElement(instrument, "quantity").text = str(quantity) payload = ET.tostring(root, encoding='unicode') headers = {"Content-Type": "application/xml"} response = session.post(order_url, header_auth=True, headers=headers, data=payload) if response.status_code == 201: response_data = response.json() if "OrderResponse" in response_data and "orderId" in response_data["OrderResponse"]: order_id = response_data["OrderResponse"]["orderId"] print(f"{order_action} order placed for {quantity} of {ticker} at {limit_price_rounded}, Order ID: {order_id}") return order_id else: print(f"Failed to place {order_action} order for {ticker}, status code: {response.status_code}, response: {response.text}") if response.status_code == 400 and "timed out" in response.text: print("Resubmitting order due to timeout...") attempt += 1 else: return None return None
最小可复现代码(需配置正确密钥)
import xml.etree.ElementTree as ET import random from rauth import OAuth1Service import webbrowser CONSUMER_KEY = 'CONSUMER_KEY' CONSUMER_SECRET = 'CONSUMER_SECRET' ETRADE_ACCOUNT_KEY = 'ACCOUNT_KEY' def initialize_etrade_oauth(): etrade = OAuth1Service( name="etrade", consumer_key=CONSUMER_KEY, consumer_secret=CONSUMER_SECRET, request_token_url="https://api.etrade.com/oauth/request_token", access_token_url="https://api.etrade.com/oauth/access_token", authorize_url="https://us.etrade.com/e/t/etws/authorize?key={}&token={}", base_url="https://api.etrade.com" ) return etrade def place_order(etrade, session, ticker, quantity, limit_price): order_url = etrade.base_url + "/v1/accounts/" + ETRADE_ACCOUNT_KEY + "/orders/place.json" client_order_id = random.randint(1000000000, 9999999999) root = ET.Element("PlaceOrderRequest") ET.SubElement(root, "orderType").text = "EQ" ET.SubElement(root, "clientOrderId").text = str(client_order_id) order = ET.SubElement(root, "Order") ET.SubElement(order, "allOrNone").text = "false" ET.SubElement(order, "priceType").text = "LIMIT" ET.SubElement(order, "orderTerm").text = "GOOD_FOR_DAY" ET.SubElement(order, "marketSession").text = "REGULAR" ET.SubElement(order, "limitPrice").text = str(limit_price) instrument = ET.SubElement(order, "Instrument") product = ET.SubElement(instrument, "Product") ET.SubElement(product, "securityType").text = "EQ" ET.SubElement(product, "symbol").text = ticker ET.SubElement(instrument, "orderAction").text = "BUY" ET.SubElement(instrument, "quantityType").text = "QUANTITY" ET.SubElement(instrument, "quantity").text = str(quantity) payload = ET.tostring(root, encoding='unicode') headers = {"Content-Type": "application/xml"} response = session.post(order_url, header_auth=True, headers=headers, data=payload) if response.status_code == 201: print(f"Buy order placed for {quantity} shares of {ticker} at limit price {limit_price}") else: print(f"Failed to place order: {response.text}") def preview_order(etrade, session, ticker, quantity, limit_price, order_action): preview_url = etrade.base_url + "/v1/accounts/" + ETRADE_ACCOUNT_KEY + "/orders/preview.json" client_order_id = random.randint(1000000000, 9999999999) root = ET.Element("PreviewOrderRequest") ET.SubElement(root, "orderType").text = "EQ" ET.SubElement(root, "clientOrderId").text = str(client_order_id) order = ET.SubElement(root, "Order") ET.SubElement(order, "allOrNone").text = "false" ET.SubElement(order, "priceType").text = "LIMIT" ET.SubElement(order, "orderTerm").text = "GOOD_FOR_DAY" ET.SubElement(order, "marketSession").text = "REGULAR" ET.SubElement(order, "limitPrice").text = str(limit_price) instrument = ET.SubElement(order, "Instrument") product = ET.SubElement(instrument, "Product") ET.SubElement(product, "securityType").text = "EQ" ET.SubElement(product, "symbol").text = ticker ET.SubElement(instrument, "orderAction").text = order_action.upper() ET.SubElement(instrument, "quantityType").text = "QUANTITY" ET.SubElement(instrument, "quantity").text = str(quantity) payload = ET.tostring(root, encoding='unicode') headers = {"Content-Type": "application/xml"} response = session.post(preview_url, header_auth=True, headers=headers, data=payload) if response.status_code == 200: response_data = response.json() if "PreviewOrderResponse" in response_data and "PreviewIds" in response_data["PreviewOrderResponse"]: preview_id = response_data["PreviewOrderResponse"]["PreviewIds"][0]["previewId"] return preview_id else: print(f"Failed to preview order, status code: {response.status_code}, response: {response.text}") return None def main(): etrade = initialize_etrade_oauth() request_token, request_token_secret = etrade.get_request_token( params={"oauth_callback": "oob", "format": "json"}) authorize_url = etrade.authorize_url.format(etrade.consumer_key, request_token) print("Please authorize the application by visiting this URL: ", authorize_url) webbrowser.open(authorize_url) verifier_code = input("Enter the verification code from the browser: ") session = etrade.get_auth_session(request_token, request_token_secret, params={"oauth_verifier": verifier_code}) ticker = "PLTR" quantity = 10 limit_price = 17 preview_id = preview_order(etrade, session, ticker, quantity, limit_price, "BUY") if preview_id is None: print("Failed to preview the order.") return place_order(etrade, session, ticker, quantity, limit_price, "BUY", preview_id) if __name__ == "__main__": main()
请求排查
恳请帮忙排查为何反复触发该超时保护错误,且重试后仍无法解决。
内容的提问来源于stack exchange,提问作者Arnav Sivakumar
相关产品推荐
相关产品推荐

